#include "tools.h"

#include <bn_fixed_point.h>
#include <bn_log.h>
#include <bn_math.h>

namespace
{
    constexpr bn::fixed piNumber{3.14};
}

int tool::convertStringToDecimalInteger(const bn::string<3>& value)
{
    int result{};

    for (int i{}; i < value.length(); ++i)
    {
        result += 10*i*(value[value.length()-1-i]-'0');
    }

    return result;
}

bn::point tool::convert2dToIsoPoint(const int x, const int y)
{
    return bn::point{x-y, (x+y)/2};
}

bn::point tool::convert2dToIsoPoint(const bn::fixed_point& point)
{
    return bn::point{point.x().integer()-point.y().integer(), (point.x().integer()+point.y().integer())/2};
}

bn::point tool::convert2dToScreenPoint(const int x, const int y, const int width, const int height)
{
    bn::point isoPoint{convert2dToIsoPoint(x,y)};
    return bn::point{isoPoint.x() - width/2, isoPoint.y() - height/2};
}
// http://shaunlebron.github.io/IsometricBlocks/
tool::isoPoint tool::convert3dToIsoPoint(const bn::fixed_point& point, const int height)
{
    const int isoX{point.x()+height};
    const int isoY{point.y()+height};
    return{
        isoX,
        isoY,
        static_cast<int>((isoX-isoY)*bn::cos(piNumber/6)),
        (isoX+isoY)/2
    };
}

bool checker::areObjectsOverlapping(const bn::fixed_rect& objectARect, const bn::fixed_rect& objectBRect, const int objectAHeight, const int objectBHeight)
{
    const tool::isoPoint objectATopLeftPoint{tool::convert3dToIsoPoint(objectARect.top_left(),objectAHeight)};
    const tool::isoPoint objectATopRightPoint{tool::convert3dToIsoPoint(objectARect.top_right(),objectAHeight)};
    const tool::isoPoint objectABottomLeftPoint{tool::convert3dToIsoPoint(objectARect.bottom_left(),objectAHeight)};

    const tool::isoPoint objectBTopLeftPoint{tool::convert3dToIsoPoint(objectBRect.top_left(),objectBHeight)};
    const tool::isoPoint objectBTopRightPoint{tool::convert3dToIsoPoint(objectBRect.top_right(),objectBHeight)};
    const tool::isoPoint objectBBottomLeftPoint{tool::convert3dToIsoPoint(objectBRect.bottom_left(),objectBHeight)};

    return
        !(objectATopLeftPoint.x >= objectBTopRightPoint.x || objectBTopLeftPoint.x >= objectATopRightPoint.x)
        && !(objectATopLeftPoint.y >= objectBBottomLeftPoint.y || objectBTopLeftPoint.y >= objectABottomLeftPoint.y)
            && !(objectATopLeftPoint.hDistance >= objectBBottomLeftPoint.hDistance || objectBTopLeftPoint.hDistance >= objectABottomLeftPoint.hDistance);
}

bool checker::isObjectAInFrontOfObjectB(const bn::fixed_rect& objectARect, const bn::fixed_rect& objectBRect, const int objectAHeight, const int objectBHeight)
{
    const tool::isoPoint objectATopLeftPoint{tool::convert3dToIsoPoint(objectARect.top_left(),objectAHeight)};
    const tool::isoPoint objectATopRightPoint{tool::convert3dToIsoPoint(objectARect.top_right(),objectAHeight)};
    const tool::isoPoint objectABottomLeftPoint{tool::convert3dToIsoPoint(objectARect.bottom_left(),objectAHeight)};

    const tool::isoPoint objectBTopLeftPoint{tool::convert3dToIsoPoint(objectBRect.top_left(),objectBHeight)};
    const tool::isoPoint objectBTopRightPoint{tool::convert3dToIsoPoint(objectBRect.top_right(),objectBHeight)};
    const tool::isoPoint objectBBottomLeftPoint{tool::convert3dToIsoPoint(objectBRect.bottom_left(),objectBHeight)};

    if (objectATopLeftPoint.x >= objectBTopRightPoint.x)
    {
        return false;
    }
    else if (objectBTopLeftPoint.x >= objectATopRightPoint.x)
    {
        return true;
    }

    if (objectATopLeftPoint.y >= objectBBottomLeftPoint.y)
    {
        return false;
    }
    else if (objectBTopLeftPoint.y >= objectABottomLeftPoint.y)
    {
        return true;
    }

    return objectATopLeftPoint.vDistance >= objectBTopLeftPoint.vDistance;
}
